<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="apple-touch-icon" href="apple-touch-icon.png">
    <link rel="shortcut icon" href="favicon.ico" />
    <link rel="manifest" href="a3.webmanifest">
    <title>A3 Joint</title>
  </head>
  <body>
    <link rel="stylesheet" href="css/main.css"/>
    <script src="js/Theme.js"></script>
    <script src="js/ammo.js/build/ammo.wasm.js"></script>
    <div class="div-fullscreen"><div id="container"></div></div>
    <script type="module">
      import * as THREE from "./js/three.js/build/three.module.js";

      import A3Class from './js/A3Class.js';

      const container = document.getElementById( 'container' );

      const a3 = new A3Class( container );

      await a3.initAmmo();

      // const va = new THREE.Vector3(0, 0, 0);
      // const vb = new THREE.Vector3(0, 0, 1);

      // console.log(va.angleTo(vb))
      // console.log(a3);
      const pos = new THREE.Vector3();
      const quat = new THREE.Quaternion( 0, 0, 0, 1 );

      let hinge;

      a3.init();
      console.log(a3.AmmoLib)

      a3.addGround(40, 0.1, 40, 'textures/grid.png');

      pos.set(0, 2, 0);
      // quat.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI / 4);

      const base = a3.createParalellepiped( 1, 1, 1, 0, pos, quat );

      
      pos.set(0, 2.25, 0);
      quat.set(0, 0, 0, 1);
      const square = a3.createParalellepiped( 0.5, 0.5, 0.5, 1, pos, quat );

      pos.set(2, 2.25, 0);
      quat.setFromAxisAngle( new THREE.Vector3(0, 1, 0), Math.PI / 2 );
      const square2 = a3.createParalellepiped( 0.5, 0.5, 0.5, 1, pos, quat );

      // const square3 = a3.createParalellepiped( 0.5, 0.5, 0.5, 0, pos, quat );

      hinge = a3.createHingeConstraint(
        base.userData.physicsBody, square.userData.physicsBody,
        new THREE.Vector3(0, 1, 0)
      );

      hinge.setLimit(-Math.PI / 2, Math.PI);
      a3.setHingeVelocity( hinge, Math.PI / 9, 1 );
      a3.updateUsers = showHingeAngle;

      const axis = new THREE.Vector3(0, 1, 0);
      const axisY = new THREE.Vector3(0, 1, 0);
      const axisZ = new THREE.Vector3(0, 0, 1);

      function showHingeAngle(){

        // const angle = a3.getAngle( base, square );
        // const angle2 = a3.getAngle( base, square2, frameInA, frameInB );

        const angle3 = a3.getHingeAngle( base, square );
        const angle4 = a3.getHingeAngle( base, square2, frameInA, frameInB, axisZ );

        console.log("角度1:", angle3.y * 180 / Math.PI);
        console.log("角度2:", angle4.z * 180 / Math.PI);

        if( angle3.y > Math.PI / 2 ){
          console.log(' 转向 ')
          a3.setHingeVelocity(hinge, -Math.PI / 9, 100 );
        }

        if( angle3.y < -Math.PI / 4 ){
          console.log(' 转向 ')
          a3.setHingeVelocity(hinge, Math.PI / 9, 100 );
        }

        if( angle4.z > Math.PI / 1.1 ){
          console.log(' 转向 ')
          a3.setHingeVelocity(hinge2, -Math.PI / 3, 100 );
        }

        if( angle4.z < -Math.PI / 1.1 ){
          console.log(' 转向 ')
          a3.setHingeVelocity(hinge2, Math.PI / 3, 100 );
        }

        // pos.copy( square2.position );
        // quat.copy( square2.quaternion );

        // const tmp = new THREE.Quaternion().setFromAxisAngle( axis, Math.PI / 4 );
        // quat.multiply( tmp );

        // pos.y += 1;

        // square3.position.copy(pos)
        // square3.quaternion.copy(quat);

        console.log("Joint-Z:", joint.getHingeAngle() * 180 / Math.PI);
        console.log("Joint-Y:", jointY.getHingeAngle() * 180 / Math.PI);
        console.log("Joint-X:", jointX.getHingeAngle() * 180 / Math.PI);

        console.log("Joint-NZ:", jointNZ.getHingeAngle() * 180 / Math.PI);
        console.log("Joint-ZNZ:", jointZNZ.getHingeAngle() * 180 / Math.PI);

      }

      pos.set( 0, 2, 0 );
      // quat.set( 0, 0, 0, 1 );
      quat.setFromAxisAngle( a3.AxisX, Math.PI / 2 );

      const frameInA = a3.getTransform( pos, quat );

      pos.set(0, 0, 0);
      // quat.set( 0, 0, 0, 1 );
      quat.setFromAxisAngle( a3.AxisX, Math.PI / 2 );


      const frameInB = a3.getTransform( pos, quat );

      const hinge2 = a3.createHingeConstraint2(
        base.userData.physicsBody, square2.userData.physicsBody,
        frameInA, frameInB
      );

      a3.setHingeVelocity( hinge2, -Math.PI / 3, 1 );

      const compound = new a3.CompoundShape();

      pos.set(0, 0, 1);
      quat.set(0, 0, 0, 1);

      const box1 = new THREE.Mesh( new THREE.BoxGeometry(.5, .5, .5), a3.createMaterial() );
      const shape1 = a3.getShape( box1.geometry );

      compound.addChild( box1, shape1, 1, pos, quat );

      pos.set(0, 1, 1);
      // quat.setFromAxisAngle( a3.AxisX, Math.PI / 2 );
      const box2 = new THREE.Mesh( new THREE.BoxGeometry(.5, .5, .5), a3.createMaterial() );
      const shape2 = a3.getShape( box2.geometry );

      compound.addChild( box2, shape2, 1, pos, quat );

      pos.set(1, 0, 1);
      // quat.setFromAxisAngle( a3.AxisX, Math.PI / 2 );
      const box3 = new THREE.Mesh( new THREE.BoxGeometry(.5, .5, .5), a3.createMaterial() );
      const shape3 = a3.getShape( box3.geometry );

      compound.addChild( box3, shape3, 1, pos, quat );

      pos.set(-1, 0, 1);
      // quat.setFromAxisAngle( a3.AxisX, Math.PI / 2 );
      const box4 = new THREE.Mesh( new THREE.BoxGeometry(.5, .5, .5), a3.createMaterial() );
      const shape4 = a3.getShape( box4.geometry );

      compound.addChild( box4, shape4, 1, pos, quat );

      pos.set(0, -1, 1);
      quat.setFromAxisAngle( a3.AxisX, Math.PI / 4 );
      const box5 = new THREE.Mesh( new THREE.BoxGeometry(.5, .5, .5), a3.createMaterial() );
      const shape5 = a3.getShape( box5.geometry );

      compound.addChild( box5, shape5, 1, pos, quat );

      pos.set(0, 10, 0);
      quat.set( 0, 0, 0, 1 );
      a3.addComoundShape( compound, pos, quat );

      console.log( compound.shape )

      pos.set(0, 0, 0);
      quat.set( 0, 0, 0, 1 );
      // quat.setFromAxisAngle( new THREE.Vector3( 0, 0, 1 ), Math.PI / 4 );
      const frameInC = a3.getTransform( pos, quat );

      pos.set(0, 0, 0);
      quat.set( 0, 0, 0, 1 );
      // quat.setFromAxisAngle( new THREE.Vector3( 0, 0, 1 ), Math.PI );
      const frameInD = a3.getTransform( pos, quat );

      const hinge3 = a3.createHingeConstraint2(
        base.userData.physicsBody, compound.threeObject.userData.physicsBody,
        frameInC, frameInD, 
      );

      // a3.setHingeVelocity( hinge3, Math.PI * 10 );2

      const actor = new a3.Actor();
      const boxActor = new THREE.Mesh( new THREE.BoxGeometry( 1, 2, 3 ), a3.createMaterial() );
      pos.set( 4, 10, 0 );
      quat.set( 0, 0, 0, 1 );
      // quat.setFromAxisAngle( new THREE.Vector3( 0, 0, 1 ), Math.PI/6 );
      actor.setFromMesh( boxActor, 1 , pos, quat);
      a3.addActor( actor );

      console.log("Three obj:", actor.threeObject.matrixWorld)

      // actor.setAngularVelocity(new THREE.Vector3( 0, 1, 0 ));
      // actor.setLinearVelocity( new THREE.Vector3 ( 0, 10, 0 ));
      // pos.z -= 2;
      // actor.setPosition( pos );
      // quat.setFromAxisAngle( a3.AxisY, Math.PI / 4 );
      // actor.setQuaternion( quat );

      ////////////////// 关节测试
      const actorParent = new a3.Actor();
      const boxParent = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), a3.createMaterial() );

      pos.set(0, 8, 0);
      quat.set( 0, 0, 0, 1 );
      actorParent.setFromMesh( boxParent, 0 , pos, quat);
      a3.addActor( actorParent );

      const actorChild = new a3.Actor();
      const boxChild = new THREE.Mesh( new THREE.BoxGeometry( .8, .8, .8 ), a3.createMaterial() );

      pos.set(0, 8, 3);
      quat.set( 0, 0, 0, 1 );
      actorChild.setFromMesh( boxChild, 1 , pos, quat);
      a3.addActor( actorChild );

      const actorChild2 = new a3.Actor();
      const boxChild2 = new THREE.Mesh( new THREE.BoxGeometry( .8, .8, .8 ), a3.createMaterial() );

      // Y轴转动
      pos.set(0, 10, 0);
      quat.set( 0, 0, 0, 1 );
      actorChild2.setFromMesh( boxChild2, 1 , pos, quat);
      a3.addActor( actorChild2 );

      // X轴转动

      const actorChild3 = new a3.Actor();
      const boxChild3 = new THREE.Mesh( new THREE.BoxGeometry( .8, .8, .8 ), a3.createMaterial() );

      pos.set(2, 8, 0);
      quat.set( 0, 0, 0, 1 );
      actorChild3.setFromMesh( boxChild3, 1 , pos, quat);
      a3.addActor( actorChild3 );

      // -Z 轴

      const actorChild4 = new a3.Actor();
      const boxChild4 = new THREE.Mesh( new THREE.BoxGeometry( .8, .8, .8 ), a3.createMaterial() );

      pos.set(0, 8, -2);
      quat.set( 0, 0, 0, 1 );
      actorChild4.setFromMesh( boxChild4, 1 , pos, quat);
      a3.addActor( actorChild4 );

      const joint = new a3.A3HingeConstraint( actorParent, actorChild );
      
      joint.setFromPivot(
        new THREE.Vector3(0, 0, 1),
        new THREE.Vector3(0, 0,  0),
        new THREE.Vector3( 0, 0, 1 ),
        new THREE.Vector3( 0, 0, 1 )
      );

      const jointY = new a3.A3HingeConstraint( actorParent, actorChild2 );
     
      jointY.setFromPivot(
        new THREE.Vector3(0, 1, 0),
        new THREE.Vector3(0, 0, 0),
        new THREE.Vector3( 0, 1, 0 ),
        new THREE.Vector3( 0, 1, 0 )
      );

      const jointX = new a3.A3HingeConstraint( actorParent, actorChild3 );
     
      jointX.setFromPivot(

        new THREE.Vector3(1, 0, 0),
        new THREE.Vector3(0, 0, 0),
        new THREE.Vector3( 1, 0, 0 ),
        new THREE.Vector3( 1, 0, 0 )

      );

      // - Z轴

      const jointNZ = new a3.A3HingeConstraint( actorParent, actorChild4 );
     
      jointNZ.setFromPivot(

        new THREE.Vector3(0, 0, -1),
        new THREE.Vector3(0, 0, 0),
        new THREE.Vector3( 0, 0, -1 ),
        new THREE.Vector3( 0, 0, -1 )

      );

      a3.addActor( jointNZ );  
      
      // Z+ Z- 轴
      const actorChild5 = new a3.Actor();
      const boxChild5 = new THREE.Mesh( new THREE.BoxGeometry( .8, .8, .8 ), a3.createMaterial() );

      pos.set(0, 8, 4);
      quat.setFromAxisAngle( a3.AxisX, Math.PI )
      actorChild5.setFromMesh( boxChild5, 1 , pos, quat);
      a3.addActor( actorChild5 );

      const jointZNZ = new a3.A3HingeConstraint( actorParent, actorChild5 );
     
      jointZNZ.setFromPivot(

        new THREE.Vector3(0, 0, 3),
        new THREE.Vector3(0, 0, 0),
        new THREE.Vector3( 0, 0, 1 ),
        new THREE.Vector3( 0, 0, -1 )

      );

      a3.addActor( jointZNZ );  
      // const square4 = a3.createParalellepiped( 0.5, 0.5, 0.5, 1, pos, quat );

      // const hinge4 = a3.createHingeConstraint(
      //   actorParent.physicsBody, square4.userData.physicsBody,
      //   new THREE.Vector3(0, 3, 0)
      // );

      a3.addActor( joint );
      a3.addActor( jointY );    
      a3.addActor( jointX );   
      
      // a3.setHingeVelocity( hinge4, 10, 100 )
      a3.onKeyDown = onKeyDown;
      a3.initInput();

      function onKeyDown( event ) {
        if( event.key === '1' ) {
          console.log("key down", joint.constraint)
          joint.setHingeVelocity( 1, 100 );
          jointY.setHingeVelocity( 1, 100 );
          jointX.setHingeVelocity( 1, 100 );
          jointNZ.setHingeVelocity( 1, 100 );
          jointZNZ.setHingeVelocity( 1, 100 );

          // actorParent.setLinearVelocity( new THREE.Vector3( 2, 0, 0 ));
          // actorChild.setAngularVelocity( new THREE.Vector3( 0, 0, -Math.PI ));
        }
        if( event.key === '2' ) {
          console.log("key down", joint.constraint)
          joint.stopHinge();
          jointY.stopHinge();
          jointX.stopHinge();
          jointNZ.stopHinge(1);
          jointZNZ.stopHinge(1);

          // actorParent.setLinearVelocity( new THREE.Vector3( 2, 0, 0 ));
          // actorChild.setAngularVelocity( new THREE.Vector3( 0, 0, 0 ));
        }
        if( event.key === '3' ) {
          joint.setHingeAngle( Math.PI / 3 );
          jointY.moveTo( Math.PI / 2, 10 );
        }
        if( event.key === '4' ){
          jointY.moveTo( -Math.PI / 4, 10 );
        }
      }

      // 从坐标轴Z 到坐标轴Y的旋转量
      console.log("Z 轴：", a3.AxisZ);
      const tquat = new THREE.Quaternion().setFromAxisAngle( a3.AxisX, Math.PI / 2 );
      console.log( tquat )
      const tx = axisZ.clone();
      tx.applyQuaternion(tquat)
      console.log( tx )
      animate();


      // container.appendChild(a3.domElement);


      function animate() {

        requestAnimationFrame( animate );

        render();

      }

      function render() {

        a3.update();

      }

    </script>
  </body>
</html>